<?php
declare(strict_types=1);

namespace App\Controller;

use App\Library\RedisLib;
use App\Model\Friend;
use App\Model\OfflineMessage;
use App\Model\SystemMessage;
use App\Model\User;
use EasySwoole\FastCache\Cache;
use Hyperf\Contract\OnCloseInterface;
use Hyperf\Contract\OnMessageInterface;
use Hyperf\Contract\OnOpenInterface;
use Swoole\Http\Request;
use Swoole\Server;
use Swoole\Websocket\Frame;
use Swoole\WebSocket\Server as WebSocketServer;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Contract\SessionInterface;

class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
    /**
     * @Inject
     * @var SessionInterface
     */
    protected $session;

    public function onMessage(WebSocketServer $server, Frame $frame): void
    {
        $data_input = json_decode($frame->data, true);
        $token      = $data_input['token'];
        $data       = [
            "type" => "token expire"
        ];
        if (!isset($token)) {
            $server->push($frame->fd, json_encode($data));
            return;
        }

        $user = RedisLib::getInstance()->get('User_token_' . $token);


        var_dump($user);
        if (empty($user)) {
            $server->push($frame->fd, json_encode($data));
            return;
        }

        //绑定fd变更状态
        RedisLib::getInstance()->setex('uid' . $user['id'], ["value" => $frame->fd], 3600);
        RedisLib::getInstance()->setex('fd' . $frame->fd, ["value" => $user['id']], 3600);
        User::where('id', $user['id'])->update(['status' => 'online']);//标记为在线


        //给好友发送上线通知，用来标记头像去除置灰
        $friend_list = Friend::where('user_id', $user['id'])->get();
        $data        = [
            "type"   => "friendStatus",
            "uid"    => $user['id'],
            "status" => 'online'
        ];
        foreach ($friend_list as $k => $v) {
            $fd = RedisLib::getInstance()->get('uid' . $v['friend_id']);//获取接受者fd
            if ($fd) {
                $server->push($fd['value'], json_encode($data));//发送消息
            }
        }
        //获取未读消息盒子数量
        $count = SystemMessage::where('user_id', $user['id'])->where('read', 0)->count();
        $data  = [
            "type"  => "msgBox",
            "count" => $count
        ];
        //检查离线消息
        $offline_messgae = OfflineMessage::where('user_id', $user['id'])->where('status', 0)->get();
        if ($offline_messgae) {
            foreach ($offline_messgae as $k => $v) {
                $fd = RedisLib::getInstance()->get('uid' . $user['id']);//获取接受者fd
                if ($fd) {
                    $server->push($fd['value'], $v['data']);//发送消息
                    OfflineMessage::where('id', $v['id'])->update(['status' => 1]);
                }
            }
        }
        $server->push($frame->fd, json_encode($data));

    }

    public function onClose(Server $server, int $fd, int $reactorId): void
    {
        $uid = Cache::getInstance()->get('fd' . $fd);


        $friend_list = Friend::where('user_id', $uid['value'])->get();
        $data        = [
            "type"   => "friendStatus",
            "uid"    => $uid['value'],
            "status" => 'offline'
        ];

        if ($friend_list) {
            foreach ($friend_list as $k => $v) {
                $result = RedisLib::getInstance()->get('uid' . $v['friend_id']);//获取接受者fd
                if ($result) {
                    $server->push($result['value'], json_encode($data));//发送消息
                }
            }
        }
        if ($uid !== false) {
            RedisLib::getInstance()->del('uid' . $uid['value']);// 解绑uid映射
        }
        RedisLib::getInstance()->del('fd' . $fd);// 解绑fd映射
        User::where('id', $uid['value'])->update(['status' => 'offline']);
    }

    public function onOpen(WebSocketServer $server, Request $request): void
    {
        $server->push($request->fd, 'Opened');
    }
}
